using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.SPOT.Emulator;
using Microsoft.SPOT.Emulator.Gpio;
using System.Threading;

namespace PureRobot.Emulators.Digi.ConnectME.JumpStart
{
    /// <summary>
    /// Form displaying a Digi Connect ME Jumpstart kit for emulation.
    /// </summary>
    public partial class JumpstartForm : Form
    {
        private Emulator emulator;

        private bool closing;

        private int gpioPort1State;
        private int gpioPort2State;
        private int gpioPort3State;
        private int gpioPort4State;
        private int gpioPort5State;
        
        private GpioPort gpio1;
        private GpioPort gpio2;
        private GpioPort gpio3;
        private GpioPort gpio4;
        private GpioPort gpio5;

        /// <summary>
        /// Initializes a new instance of the <see cref="JumpstartForm"/> class.
        /// </summary>
        /// <param name="emulator">The emulator.</param>
        public JumpstartForm(Emulator emulator)
        {
            InitializeComponent();

            this.emulator = emulator;

            this.closing = false;

            gpioPort1State = 0;
            gpioPort2State = 0;
            gpioPort3State = 0;
            gpioPort4State = 0;
            gpioPort5State = 0;

            this.FormClosing += new FormClosingEventHandler(JumpstartForm_FormClosing);

            gpio1 = (GpioPort)emulator.FindComponentById("GpioPin1");
            gpio1.OnGpioActivity += new GpioActivity(gpio_OnGpioActivity);
            gpio2 = (GpioPort)emulator.FindComponentById("GpioPin2");
            gpio2.OnGpioActivity += new GpioActivity(gpio_OnGpioActivity);
            gpio3 = (GpioPort)emulator.FindComponentById("GpioPin3");
            gpio3.OnGpioActivity += new GpioActivity(gpio_OnGpioActivity);
            gpio4 = (GpioPort)emulator.FindComponentById("GpioPin4");
            gpio4.OnGpioActivity += new GpioActivity(gpio_OnGpioActivity);
            gpio5 = (GpioPort)emulator.FindComponentById("GpioPin5");
            gpio5.OnGpioActivity += new GpioActivity(gpio_OnGpioActivity);
            
        }

        void JumpstartForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            closing = true;
        }

        void gpio_OnGpioActivity(GpioPort sender, bool edge)
        {
            switch (sender.ComponentId)
            {
                case "GpioPin1":
                    {
                        Interlocked.Exchange(ref gpioPort1State, edge ? 1 : 0);
                        break;
                    }
                case "GpioPin2":
                    {
                        Interlocked.Exchange(ref gpioPort2State, edge ? 1 : 0);
                        break;
                    }
                case "GpioPin3":
                    {
                        Interlocked.Exchange(ref gpioPort3State, edge ? 1 : 0);
                        break;
                    }
                case "GpioPin4":
                    {
                        Interlocked.Exchange(ref gpioPort4State, edge ? 1 : 0);
                        break;
                    }
                case "GpioPin5":
                    {
                        Interlocked.Exchange(ref gpioPort5State, edge ? 1 : 0);
                        break;
                    }
            }
        }

        private void pictureBoxSwitch1_Click(object sender, EventArgs e)
        {
            switchGpio(pictureBoxSwitch1, gpio1);
        }

        private void pictureBoxSwitch2_Click(object sender, EventArgs e)
        {
            switchGpio(pictureBoxSwitch2, gpio2);
        }

        private void pictureBoxSwitch3_Click(object sender, EventArgs e)
        {
            switchGpio(pictureBoxSwitch3, gpio3);
        }

        private void pictureBoxSwitch4_Click(object sender, EventArgs e)
        {
            switchGpio(pictureBoxSwitch4, gpio4);
        }

        private void pictureBoxSwitch5_Click(object sender, EventArgs e)
        {
            switchGpio(pictureBoxSwitch5, gpio5);
        }

        private void JumpstartForm_MouseClick(object sender, MouseEventArgs e)
        {
            if (pictureBoxSwitch1.Bounds.Contains(e.Location))
            {
                switchGpio(pictureBoxSwitch1, gpio1);
            }
            else if (pictureBoxSwitch2.Bounds.Contains(e.Location))
            {
                switchGpio(pictureBoxSwitch2, gpio2);
            }
            else if (pictureBoxSwitch3.Bounds.Contains(e.Location))
            {
                switchGpio(pictureBoxSwitch3, gpio3);
            }
            else if (pictureBoxSwitch4.Bounds.Contains(e.Location))
            {
                switchGpio(pictureBoxSwitch4, gpio4);
            }
            else if (pictureBoxSwitch5.Bounds.Contains(e.Location))
            {
                switchGpio(pictureBoxSwitch5, gpio5);
            }
        }

        private void JumpstartForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (pictureBoxSwitch1.Bounds.Contains(e.Location))
            {
                setSwitchCursor(pictureBoxSwitch1);
            }
            else if (pictureBoxSwitch2.Bounds.Contains(e.Location))
            {
                setSwitchCursor(pictureBoxSwitch2);
            }
            else if (pictureBoxSwitch3.Bounds.Contains(e.Location))
            {
                setSwitchCursor(pictureBoxSwitch3);
            }
            else if (pictureBoxSwitch4.Bounds.Contains(e.Location))
            {
                setSwitchCursor(pictureBoxSwitch4);
            }
            else if (pictureBoxSwitch5.Bounds.Contains(e.Location))
            {
                setSwitchCursor(pictureBoxSwitch5);
            }
            else
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void setSwitchCursor(PictureBox pictureBox)
        {
            if (pictureBox.Visible)
            {
                this.Cursor = Cursors.PanNW;
            }
            else
            {
                this.Cursor = Cursors.PanSE;
            }
        }

        private void switchGpio(PictureBox pictureBox, GpioPort gpioPort)
        {
            bool currentState = pictureBox.Visible;

            //Reverse the current visibility of the switch image
            pictureBox.Visible = !currentState;

            //Write the new state to the GPIO port
            gpioPort.Write(!currentState);

            //Update the cursor
            setSwitchCursor(pictureBox);
        }

        private void timerStartGpioMonitor_Tick(object sender, EventArgs e)
        {
            timerStartGpioMonitor.Enabled = false;
            while (closing==false)
            {
                //Check for changes in IO state
                checkState(gpioPort1State, pictureBoxLight1);
                checkState(gpioPort2State, pictureBoxLight2);
                checkState(gpioPort3State, pictureBoxLight3);
                checkState(gpioPort4State, pictureBoxLight4);
                checkState(gpioPort5State, pictureBoxLight5);

                Application.DoEvents();
            }
        }

        private void checkState(int gpioState, PictureBox lightImage)
        {
            if ((gpioState != 0) != lightImage.Visible)
            {
                lightImage.Visible = (gpioState != 0);
                this.Invalidate(lightImage.Bounds);
            }
        }
    }
}